package img_uploader

import (
	"errors"
	"fmt"
	"net/http"
	"os"
	"strings"
)

var jsonPrefix = "json:"

var ExtUploader = make(map[string]ImgUploader)

func init() {
	ExtUploader["https://baijiahao.baidu.com/pcui/picture/upload"] = &BaijiahaoImgUploader{}
}

type ImgUploader interface {
	IsCookieValid() error       // 验证当前配置是否正确，配置错误直接返回 err
	Input(imgPaths []string)    // 输入要传入的图片的路径
	Transformer() error         // 对图片进行编码处理
	Upload() error              // 上传图片
	GetUploadResults() []string // 获取上传结果
	SetUploader(uploader *GenericImgUploader)
}

type GenericImgUploader struct {
	Version         string            `json:"Version,omitempty"`
	Name            string            `json:"Name,omitempty"`
	DestinationType string            `json:"DestinationType,omitempty"`
	RequestMethod   string            `json:"RequestMethod,omitempty"`
	RequestURL      string            `json:"RequestURL,omitempty"`
	Headers         map[string]string `json:"Headers,omitempty"`
	Body            string            `json:"Body,omitempty"`
	FileFormName    string            `json:"FileFormName,omitempty"`
	URL             string            `json:"URL,omitempty"`
	ValidateURL     string            `json:"ValidateURL,omitempty"`
	ThumbnailURL    string            `json:"ThumbnailURL,omitempty"`
	ErrorMessage    string            `json:"ErrorMessage,omitempty"`
	imagePaths      []string
	imageUrls       []string
	imagesData      [][]byte
	headers         map[string][]string
}

func (u *GenericImgUploader) IsCookieValid() error {
	u.headers = make(map[string][]string)
	for k, v := range u.Headers {
		u.headers[k] = []string{v}
	}
	return nil
}
func (u *GenericImgUploader) Input(imgPaths []string) { u.imagePaths = imgPaths }
func (u *GenericImgUploader) Transformer() error {
	//for _, imagePath := range u.imagePaths {
	//	err := func() error {
	//		_, err := os.Stat(imagePath)
	//		if err != nil {
	//			return err
	//		}
	//		file, err := os.OpenFile(imagePath, os.O_RDONLY, 0755)
	//		if err != nil {
	//			return err
	//		}
	//		defer file.Close()
	//		bytes, err := io.ReadAll(file)
	//		if err != nil {
	//			return err
	//		}
	//		u.imagesData = append(u.imagesData, bytes)
	//		return nil
	//	}()
	//	if err != nil {
	//		return err
	//	}
	//}
	return nil
}
func (u *GenericImgUploader) Upload() error {
	for _, imagePath := range u.imagePaths {
		err := func() error {
			file, err := os.Open(imagePath)
			if err != nil {
				return err
			}
			if u.Body != "MultipartFormData" {
				return fmt.Errorf("the post body format {%s} is not supported at present", u.Body)
			}
			body, contentType, err := createMultipartFormData(file, u.FileFormName)
			if err != nil {
				return err
			}
			req, err := http.NewRequest(u.RequestMethod, u.RequestURL, body)
			if err != nil {
				return err
			}
			req.Header = u.headers
			req.Header.Set("Content-Type", contentType)
			resp, err := http.DefaultClient.Do(req)
			if err != nil {
				return err
			}
			defer resp.Body.Close()

			urlFormat := strings.Trim(u.URL, "{}")

			if strings.HasPrefix(urlFormat, jsonPrefix) {
				path := strings.TrimLeft(urlFormat, jsonPrefix)
				result, err := asJson(resp)
				if err != nil {
					return err
				}
				imgUrl, err := getStringInJson(&result, path)
				if err != nil {
					errMsgFmt := strings.Trim(u.ErrorMessage, "{}")
					errMsgPath := strings.TrimLeft(errMsgFmt, jsonPrefix)
					errMsg, err2 := getStringInJson(&result, errMsgPath)
					if err2 == nil {
						return fmt.Errorf(errMsg)
					}
					return err
				}
				u.imageUrls = append(u.imageUrls, imgUrl)
				if err != nil {
					return err
				}
			} else {
				return fmt.Errorf("the url format {%s} is not supported at present", urlFormat)
			}
			return nil
		}()

		if err != nil {
			return err
		}
	}
	return nil
}
func (u *GenericImgUploader) GetUploadResults() []string {
	var result []string
	if len(u.imageUrls) > 0 {
		result = append(result, "Upload Success:")
		result = append(result, u.imageUrls...)
	} else {
		result = append(result, "Upload Failed:\nUnknown Error")
	}
	return result
}
func (u *GenericImgUploader) SetUploader(uploader *GenericImgUploader) {}

type BaijiahaoImgUploader struct {
	*GenericImgUploader
}

func (u *BaijiahaoImgUploader) IsCookieValid() error {
	_ = u.GenericImgUploader.IsCookieValid() // 相当于先调用"父类"的方法，以初始化headers字段
	if u.ValidateURL == "" {
		return nil // 不配置验证链接，则默认身份合法，通过后续上传流程反馈错误信息
	}
	req, err := http.NewRequest("GET", u.ValidateURL, nil)
	if err != nil {
		return err
	}
	req.Header = u.headers
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	result, err := asJson(resp)
	if err != nil {
		return err
	}
	errno, ok := result["errno"].(float64)
	if !ok {
		return errors.New("type error: errno is not a number")
	}
	if int(errno) == 0 {
		return nil
	} else {
		return errors.New(result["errmsg"].(string))
	}
}
func (u *BaijiahaoImgUploader) SetUploader(uploader *GenericImgUploader) {
	u.GenericImgUploader = uploader
}
